﻿using System.Windows;
using System.Windows.Controls;
using Dsl.Ped.Framework.Extensions;

namespace Dsl.Ped.Framework.Projections.ObjectProjections.Headered
{
    /// <summary>
    /// <see cref="HeaderedProjection"/> organize content into a block as follows:
    /// Vertical Orientation:
    ///     #HeaderProjection#
    ///     #ContentProjection#
    /// 
    /// Horizontal Orientation:
    ///     #HeaderProjection# #ContentProjection#
    /// </summary>
    public class HeaderedProjection : ContentControl
    {
        #region Fields

        /// <summary>
        /// Gets or sets the <see cref="ContentPresenter"/> of the content of the #HeaderProjection# 
        /// </summary>
        private ContentPresenter HeaderProjectionPresenter { get; set; }

        /// <summary>
        /// Gets or sets the <see cref="ContentPresenter"/> of the content of the #ContentProjection#
        /// </summary>
        private ContentPresenter ContentPresenter { get; set; }

        /// <summary>
        /// <see cref="DependencyProperty"/> that defines whether the whole projection is organized horizontally or vertically
        /// </summary>
        public static DependencyProperty OrientationProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that refers to the object indented as a #HeaderProjection#
        /// </summary>
        public static DependencyProperty HeaderProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that refers to the <see cref="Style"/> of the #HeaderProjection#
        /// </summary>
        public static DependencyProperty HeaderStyleProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that refers to the vertical alignment of the #HeaderProjection#
        /// </summary>
        public static DependencyProperty VerticalHeaderAlignmentProperty;

        /// <summary>
        /// <see cref="DependencyProperty"/> that referes to the horizontal alignment of the #HeaderProjection#
        /// </summary>
        public static DependencyProperty HorizontalHeaderAlignmentProperty;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes static members of the <see cref="HeaderedProjection"/> class.
        /// </summary>
        static HeaderedProjection()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(HeaderedProjection), new FrameworkPropertyMetadata(typeof(HeaderedProjection)));

            OrientationProperty = DependencyProperty.Register(
                "Orientation", typeof(Orientation), typeof(HeaderedProjection), new FrameworkPropertyMetadata(Orientation.Horizontal));

            HeaderProperty = DependencyProperty.Register(
                "Header", typeof(object), typeof(HeaderedProjection), new FrameworkPropertyMetadata(null));

            HeaderStyleProperty = DependencyProperty.Register(
                "HeaderStyle", typeof(Style), typeof(HeaderedProjection), new FrameworkPropertyMetadata(null));

            VerticalHeaderAlignmentProperty = DependencyProperty.Register(
                "VerticalHeaderAlignment", typeof(VerticalAlignment), typeof(HeaderedProjection), new FrameworkPropertyMetadata(VerticalAlignment.Center));

            HorizontalHeaderAlignmentProperty = DependencyProperty.Register(
                "HorizontalHeaderAlignment", typeof(HorizontalAlignment), typeof(HeaderedProjection), new FrameworkPropertyMetadata(HorizontalAlignment.Center));
        }

        #endregion

        #region Members

        /// <summary>
        /// Gets or sets the orientation of the projection
        /// </summary>
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        /// <summary>
        /// Gets or sets the object that is supposed to be a header
        /// </summary>
        public object Header
        {
            get { return (object)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }

        /// <summary>
        /// Gets or sets the style applied on header
        /// </summary>
        public Style HeaderStyle
        {
            get { return (Style)this.GetValue(HeaderStyleProperty); }
            set { SetValue(HeaderStyleProperty, value); }
        }

        /// <summary>
        /// Gets or sets the vertical alignment of the header
        /// </summary>
        public VerticalAlignment VerticalHeaderAlignment
        {
            get { return (VerticalAlignment)this.GetValue(VerticalHeaderAlignmentProperty); }
            set { SetValue(VerticalHeaderAlignmentProperty, value); }
        }

        /// <summary>
        /// Gets or sets the horizontal alignment of the header
        /// </summary>
        public HorizontalAlignment HorizontalHeaderAlignment
        {
            get { return (HorizontalAlignment)this.GetValue(HorizontalHeaderAlignmentProperty); }
            set { SetValue(HorizontalHeaderAlignmentProperty, value); }
        }

        #endregion

        #region Methods

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.HeaderProjectionPresenter = (ContentPresenter)GetTemplateChild("PART_HeaderProjection");
            this.HeaderProjectionPresenter.SetContentBasedOnType(this.Header);

            this.ContentPresenter = (ContentPresenter)this.GetTemplateChild("PART_Content");
            this.ContentPresenter.SetContentBasedOnType(this.Content);
        }

        #endregion
    }
}
